package ar.edu.itba.pod.legajo48240.simulation;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

import org.apache.log4j.Logger;

import ar.edu.itba.balance.api.AgentsBalancer;
import ar.edu.itba.balance.api.NodeAgent;
import ar.edu.itba.balance.api.NotCoordinatorException;
import ar.edu.itba.pod.agent.runner.Agent;
import ar.edu.itba.pod.legajo48240.event.LocalEventDispatcher;
import ar.edu.itba.pod.legajo48240.model.Host;
import ar.edu.itba.pod.legajo48240.utils.Net;
import ar.edu.itba.pod.multithread.EventDispatcher;
import ar.edu.itba.pod.multithread.LocalSimulation;
import ar.edu.itba.pod.time.TimeMapper;


public class DistributedSimulationManager  extends LocalSimulation{
	
	
	private final EventDispatcher dispatcher;
	private final Host localhost;
	private final Logger LOGGER = Logger.getLogger(DistributedSimulationManager.class);
	
	public DistributedSimulationManager (TimeMapper timeMapper, Host localhost) {
		super(timeMapper);
		this.dispatcher=new LocalEventDispatcher(localhost);
		this.localhost=localhost;
	}
	
	public EventDispatcher dispatcher() {
		return this.dispatcher;
	}
	
	@Override
	public void add(Agent agent) {
		checkNotNull(agent, "Agent cannot be null");
		checkArgument(!this.getAgentsRunning().contains(agent), "Cannot add the same agent twice");
		boolean coordinatorNotMatch=false;
		
		while( !coordinatorNotMatch ){
			try {
				AgentsBalancer balancer = Net.getBalancer(localhost.getCoordinator());
				balancer.addAgentToCluster(new NodeAgent(localhost.node(), agent));
				coordinatorNotMatch=true;
				LOGGER.info("AGREGUÉ AGENTE " + agent.getClass().getSimpleName());
			} catch (NotCoordinatorException e) {
				LOGGER.info("NOT COORDINATOR... debería:" + e.getNewCoordinator());
				localhost.setCoordinator(e.getNewCoordinator());
			} catch (Exception e) {
				LOGGER.info("EXCEPTION:");
				Net.disconnectFromGroup(localhost, localhost.getCoordinator());
				e.printStackTrace();
			}
		}
	}
	
	public void localAdd(Agent agent){
		super.add(agent);
	}

}